package com.sentiment.algorithm;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import org.wltea.analyzer.cfg.Configuration;
import org.wltea.analyzer.cfg.DefaultConfig;
import org.wltea.analyzer.core.IKSegmenter;
import org.wltea.analyzer.core.Lexeme;
public class LshCorePageNo {

	/*
     * 以下key，signatureLength为二个参数
     * 二个参数均需要不断调试，以获得最佳数值
     * key：  k-shingle的k值大小 ，请取值为3到一句话的平均长度的3/4进行调试
     * signatureLength：签名长度，根据实际情况取值，如果是一篇文章，值可能需要比较大，但是不要超过80
     * 该版本使用了分词和接口分开
     */
    private int key=7;
    private int signatureLength=80;
    /*
     * threadhold:参数 输出为0-100的整数，代表百分比，例如输入11，则为11%
     */
    
    private int threadhold=11;

    /*
     * 以下参数自动获得，保留
     */
    
    private int keyContinue;         //桶的大小
    private String articShing;       //临时文件名
    private int numberOfText;        //文章数目
    private ArrayList<String> articls =new ArrayList<String>();
    private String pattern;          //输入的需要查从文件
    private Matrix signNatureMap;    //签名矩阵
    private String simi="";          //相似度字符串
    private ArrayList<ArrayList<Integer>>  pageShingling = new
              ArrayList<ArrayList<Integer>>();         //k-shingle后每篇文章对应的桶值

    private HashMap<Integer,String> bucket = new HashMap<Integer, String>();   //桶
    private HashMap<String,Integer> store = new HashMap<String, Integer>();    

       
    /*
     * 对每篇文章分句的预处理
     */
    public String getSentences(String str) {
		str = str.replaceAll("-", "");
		return str.replaceAll("[。！？；]", "-");
	}

    /*
     * 建表过程，针对所每篇文章建表
     */
    public void createTableSin(String pagetext,String textname,int i){
    	numberOfText++;
    	articls.add(textname);
    	ArrayList<Integer> arrayList=new ArrayList<Integer>();
        String regex="^[\\u0020\\u3000]*$";
        String[] paras=pagetext.split("\n");
        int paras_length=paras.length;
        int koo=0;
        while(koo<paras_length){

            String text=paras[koo].replaceAll(regex,"");
        	koo++;

            if(text.trim().isEmpty()||"".equals(text.trim())){
                continue;
            }

            String[] sens=getSentences(text).split("-");

            int senLength=sens.length;


            
            for(int j=0;j<senLength;j++){

                String s=sens[j];
                IKSegmenter analyzer = new IKSegmenter(new StringReader(s),true);
                Lexeme le = null;
        		try {
        			while ((le = analyzer.next()) != null){
        				String shingstr=le.getLexemeText();
        				if(!store.containsKey(shingstr)){
        					
                            bucket.put(keyContinue,shingstr);
                            store.put(shingstr,keyContinue);
                            keyContinue++;
                        }
        				arrayList.add(store.get(shingstr));
        			}
        		} catch (IOException e) {
        			e.printStackTrace();
        		}
                
        
           }
        }
        pageShingling.add(arrayList);
    }
    
    
    /*
     * 初始化签名矩阵，设置值为最大Integer
     */
    
    public void setupSignature(){
        signNatureMap=new Matrix(numberOfText,signatureLength);
        for(int i=0;i<numberOfText;i++){
            for (int j=0;j<signatureLength;j++){
                signNatureMap.setNumberWithRowAndCol(i,j,Integer.MAX_VALUE);
            }
        }
    }
    
    /*
     * hashFuction过程，由hash函数组决定
     */
    public int hashFuction(int primePoint,int number){
      return (PrimeNumber.number[primePoint]*number+1)%keyContinue;
  }

    /*
     * 判断是否为有效的素数
     */
  public boolean isRightPrime(int primePoint){
      if((keyContinue%PrimeNumber.number[primePoint])==0){
          return false;
      }
      return true;
  }
    
    /*
     * 最小签名矩阵计算，初始化函数组合计算最小签名，获得一个最小签名的集合
     */
      public void minHash(){
          setupSignature();
          int primePoint=0;
          int [] indexOfPrime= new int[signatureLength];
          for(int i=0;i<signatureLength;primePoint++){
              if(isRightPrime(primePoint)){
                  indexOfPrime[i]=primePoint;
//                  System.out.print(primePoint + ",");
                  i++;
              }
          }

          for(int i=0;i<numberOfText;i++){
              ArrayList<Integer> arrayList=pageShingling.get(i);
              for(Integer tem:arrayList){
                  for(int j=0;j<signatureLength;j++){
                      int tempPrime=hashFuction(indexOfPrime[j],tem);
                      if(signNatureMap.getNumberWithLineAndRow(i,j)>tempPrime){
                          signNatureMap.setNumberWithRowAndCol(i,j,tempPrime);
                      }
                  }
              }
          }

      }
      
      /*
       * 根据文章的特性，简化的Lsh操作
       * numberOfText：文章数目
       * 直接计算出相似度，低于阙值不输出
       */
      
      public void handleLsh(){
          

          for(int i=0;i<numberOfText-1;i++){
          	int k=0;
              for(int j=0;j<signatureLength;j++){
              	if(signNatureMap.getNumberWithLineAndRow(i, j)==
              			signNatureMap.getNumberWithLineAndRow(numberOfText-1,j)){
              			k++;
              	}
              }
              double si=(double)k/(double)signatureLength;
              si=si*100;
              if(si>(double)threadhold){
              	StringBuilder strb=new StringBuilder();
                  strb.append("0"+"\t"+"0"+"\t");
                  String temp_f=articls.get(i);
                  strb.append(temp_f+"\t"+"0"+"\t"+"0"+"\t");
                  String mi=(int)si+"%";
                  
                  strb.append(mi);
                  strb.append("\n");
                  simi+=strb.toString();
              }
              
          }

      }
      public String writeToDBSimi(){
          return simi;
      }
      
      /*
       * 输出文章的相似比例
       */
      public void writeToFileSimi(String path){
          try{
              PrintWriter output=new PrintWriter(new BufferedWriter
                        (new FileWriter(path)));

              
              output.println(simi);

              output.close();
          }catch (Exception e){
              e.printStackTrace();
          }
      }
      
      public void run(){
    	  minHash();
          handleLsh();
      }
}
